#define _USE_MATH_DEFINES
#include <math.h>
#include "renderwidget.h"
#include <QTimer>
#include <QPainter>
#include <QPaintEvent>
#include <QWidget>
#include "qdebug.h"
#include "qsvgrenderer.h"
#include "qtooltip.h"
#include "dataentry.h"

RenderWidget::RenderWidget(QWidget *parent, Graph* graph): QGLWidget(QGLFormat(QGL::SampleBuffers), parent), graph(graph) {
    setAutoFillBackground(false);
	useBackground(true);

	background = QBrush(Qt::white);
	
	//setMouseTracking(true);
}

RenderWidget::~RenderWidget(void) {
}

void RenderWidget::resizeEvent(QResizeEvent* event) {
	QSize old = event->oldSize();
	QSize now = event->size();
	if(visibleBackgroundImage && (qAbs(old.width() - now.width()) > 100 || qAbs(old.height() - now.height()) > 100)) {
		setBackgroundImage(backgroundImagePath);
	}
}

void RenderWidget::mouseMoveEvent(QMouseEvent *event) {
	//would be nice to show a tooltip here!
	/*bool mouseOver = false;
	for(int i = 0; i < nodePositions.size(); i++) {
		if ((nodePositions[i] - event->pos()).manhattanLength() <= 1.5) {
			QToolTip::showText(event->globalPos(), graph->getNodes()[i]->info());
			mouseOver = true;
			continue;
		}
	}

	if(!mouseOver) {
		QToolTip::hideText();
        event->ignore();
	}*/
 }

void RenderWidget::setNodeProperties(double radius, QColor fillColor, QColor lineColor, double lineWidth) {
	nodeRadius = radius;
	nodeBrush = QBrush(fillColor);
    nodePen = QPen(lineColor);
    nodePen.setWidthF(lineWidth);
}

void RenderWidget::setEdgeProperties(QColor lineColor, double lineWidth) {
	edgePen = QPen(lineColor);
	edgePen.setWidthF(lineWidth);
}

void RenderWidget::setBackgroundImage(QString path) {
	useBackground(true);
	backgroundImagePath = path;

	if(path.endsWith("svg")) {
		QSvgRenderer svg(path);
		QImage img(width(), height(), QImage::Format_ARGB32);
		img.fill(Qt::white);
		QPainter painter(&img);
		svg.render(&painter);
		backgroundImage = QPixmap::fromImage(img); 
	} else if(path.endsWith("png") || path.endsWith("jpg")) {
		backgroundImage = QPixmap(path);
	} else {
		useBackground(false);
		backgroundImagePath = "";
	}
}

void RenderWidget::setBackgroundColor(QColor color) {
	background = QBrush(color);
}

/**
 * get coordinate in current window size from point in normalized coordinates
 * point is normalized to [0;1] range -> multiply by widget dimensions
**/
QPoint RenderWidget::getWindowCoordinate(QPointF point) {
	return QPoint(point.x() * width(), point.y() * height());
}

void RenderWidget::paintEvent(QPaintEvent *event) {
    QPainter painter;
    painter.begin(this);
	painter.setRenderHint(QPainter::Antialiasing);
    paint(&painter, event);
    painter.end();
}

void RenderWidget::paint(QPainter *painter, QPaintEvent *event) {
	if(visibleBackgroundImage)
		painter->drawPixmap(event->rect(), backgroundImage);
	else
		painter->fillRect(event->rect(), background);

	//this code is super basic, nodes might be drawn in edges loop or something

    painter->setPen(edgePen);
	
	if(visibleEdges) { /*draw edges*/
		QList<Edge*> edges = graph->getEdges();

		for(int iEdge = 0; iEdge < edges.length(); iEdge++) {
			Edge* edge		= edges[iEdge];

			QPoint start	= getWindowCoordinate(edge->getFirstNode()->coord());
			QPoint end		= getWindowCoordinate(edge->getLastNode()->coord());
			
			/*if wrapEdges: draw edges between points close to left and right border as though wrapping around earth
			* _______________             _______________
			* |             |             |             |
			* |             | instead of  |             | 
			* |-*       *---|             | *-------*   |
			* |_____________|             |_____________|
			**/
			if(wrap && qAbs(start.x() - end.x()) > width() / 2) { //do wrap for edges with greater distance than half of window width
				
				QPoint left, right; //determine which point is left and which is right
				(start.x() < end.x()) ? left = start, right = end : left = end, right = start;

				//calculate percentage of total line going from left point to border: divide left coordinate by total length of line
				double leftPercent = left.x() / (left.x() + (width() - right.x())); 

				//determine y coordinate of intersection by interpolating between y values according to above percentage
				double yInterp = left.y() - leftPercent * (left.y() - right.y());

				painter->drawLine(left, QPointF(0, yInterp));
				painter->drawLine(right, QPointF(width(), yInterp));
			} else {
				painter->drawLine(start, end);
			}
		}
	}

	painter->setBrush(nodeBrush);
    painter->setPen(nodePen);

	if(visibleNodes) { /*draw nodes*/
		QList<Node*> nodes = graph->getNodes();

		for(int iNode = 0; iNode < nodes.length(); iNode++) {
			QPointF position = nodes[iNode]->coord();
			
			double radius = qMax(log(nodes[iNode]->getDegree()), nodeRadius);
			painter->drawEllipse((QPointF)getWindowCoordinate(position), radius, radius);
		}
	}
	
} 